package com.irdstudio.efp.esb.api.service.sed;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.irdstudio.basic.framework.core.constant.ESBConstant;
import com.irdstudio.basic.framework.core.constant.EsbRetCodeStandard;
import com.irdstudio.efp.esb.api.common.EsbRespServiceBeanCreator;
import com.irdstudio.efp.esb.common.constant.EsbBizEnums;
import com.irdstudio.efp.esb.common.constant.EsbSysHeadEnums;
import com.irdstudio.efp.esb.common.constant.RespRetCode;
import com.irdstudio.efp.esb.common.server.req.EsbReqServiceBean;
import com.irdstudio.efp.esb.common.server.resp.EsbRespServiceBean;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* 普税贷产品对税e贷产品的此部分代码做了复用
* 说明：为了保证功能的复用性、提升开发的工作效率，对该代码进行了复用
* 评估是否会影响线上功能：否
* 评估时间：2020/5/25
* 处理方案：保留复用
*/

/**
 * 需求编号：【2019D0519】
 * 问题编号：【】
 * 提供一些关于sed的通用操作
 * @author xiaojunhui
 * @version 0.1
 * @description TODO
 * @date 2019/5/9 11:14
 */
@Service
public class SedCommonService<R> {

    private static Logger logger = LoggerFactory.getLogger(SedCommonService.class);

    /**
     * 默认页
     */
    private final int DEFAULT_PAGE_NO = 1;

    /**
     * 默认大小
     */
    private final int DEFAULT_PAGE_SIZE=9999;

    /**
     * 预言一个字符串为空
     */
    private Predicate<String> strIsEmptyPredicate=(s)->StringUtils.isEmpty(s);

    /**
     * 函数名数组
     */
    private final String[] mNameArr=new String[]{"setRetCode","setRetStCd","setRetMsg"};

    /**
     * 预言函数名在数组中
     */
    private final Predicate<Method> mNamePredicate=(m)-> Arrays.asList(mNameArr).contains(m.getName());


    /**
     * 预言函数名为第一或者第二个
     */
    private final Predicate<Method> retCodePredicate=(m)->m.getName().equals(mNameArr[0])||m.getName().equals(mNameArr[1]);

    /**
     * 预言函数名为第三个
     */
    private final Predicate<Method> retMsgPredicate=(m)->m.getName().equals(mNameArr[2]);


    public EsbRespServiceBean getSucessBean(EsbReqServiceBean esbReqServiceBean, R respBean, RespRetCode respRetCode){
        Stream.of(respBean.getClass().getDeclaredMethods()).filter(mNamePredicate).collect(Collectors.toList()).forEach((method -> {
            try {
                if (retCodePredicate.test(method)) {
                    method.invoke(respBean,respRetCode.getCode());
                }
                if (retMsgPredicate.test(method)) {
                    method.invoke(respBean,respRetCode.getDesc());
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }));
        return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
                JSONObject.toJSONString(respBean, SerializerFeature.WriteMapNullValue,SerializerFeature.WriteNullListAsEmpty,SerializerFeature.WriteNullStringAsEmpty,SerializerFeature.WriteNullNumberAsZero,SerializerFeature.WriteMapNullValue),
                EsbSysHeadEnums.RetStEnum.SUCCESS.getCode(),
                EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE(),respRetCode.getDesc());
    }

    /**
     *
     * 发生异常时候封装EsbRespServiceBean对象
     * @param esbReqServiceBean
     * @param exception 异常信息
     * @param respBean 报文返回封装对象
     * @param respRetCode 相应类型
     * @return
     */
    public EsbRespServiceBean getEsbRespServiceBeanByException(EsbReqServiceBean esbReqServiceBean, Exception exception, R respBean, RespRetCode respRetCode, EsbRetCodeStandard esbRetCodeStandard) {
        logger.error(respBean.getClass().getSimpleName()+"查询发生异常："+exception.getMessage());
        //需要反馈异常信息给esb
        logger.info(respBean.getClass().getSimpleName()+"查询发生异常处理开始");
        //通过反射设置失败状态码
         Stream.of(respBean.getClass().getDeclaredMethods()).filter(mNamePredicate).collect(Collectors.toList()).forEach((method -> {
            try {
                if (retCodePredicate.test(method)) {
                    //method.invoke(respBean,respRetCode.getCode());
                    method.invoke(respBean,esbRetCodeStandard.getValue());
                }
                if (retMsgPredicate.test(method)) {
                    method.invoke(respBean,exception.getMessage());
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }));
        logger.info(respBean.getClass().getSimpleName()+"查询发生异常处理结束");
        exception.printStackTrace();
        return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
                JSONObject.toJSONString(respBean, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullNumberAsZero, SerializerFeature.WriteMapNullValue),
                ESBConstant.SUCCESS,
                esbRetCodeStandard.getValue(),
                exception.getMessage());
    }

    /**
     * 获取offset limit currentQueryPageNo
     * @param pageNo
     * @param pageSize
     * @return
     */
    public int[] getOffsetLimt(String pageNo,String pageSize) {

        int queryPageNo=DEFAULT_PAGE_NO;
        int limt=DEFAULT_PAGE_SIZE;
        if (!strIsEmptyPredicate.test(pageNo)) {
            queryPageNo = Integer.parseInt(pageNo);
        }
        if (!strIsEmptyPredicate.test(pageSize)) {
            limt = Integer.parseInt(pageSize);
        }

        return new int[]{(queryPageNo-1)*limt,limt,queryPageNo};
    }



}
